{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Title: #Number of Valid Words in a Sentence"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Difficulty: #Easy"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Category Title: #Algorithms"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Tag Slug: #string"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Name Translated: #字符串"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Solution Name: countValidWords"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Translated Title: #句子中的有效单词数"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Translated Content:\n",
    "<p>句子仅由小写字母（<code>'a'</code> 到 <code>'z'</code>）、数字（<code>'0'</code> 到 <code>'9'</code>）、连字符（<code>'-'</code>）、标点符号（<code>'!'</code>、<code>'.'</code> 和 <code>','</code>）以及空格（<code>' '</code>）组成。每个句子可以根据空格分解成 <strong>一个或者多个 token</strong> ，这些 token 之间由一个或者多个空格 <code>' '</code> 分隔。</p>\n",
    "\n",
    "<p>如果一个 token 同时满足下述条件，则认为这个 token 是一个有效单词：</p>\n",
    "\n",
    "<ul>\n",
    "\t<li>仅由小写字母、连字符和/或标点（不含数字）\b组成。</li>\n",
    "\t<li><strong>至多一个</strong> 连字符 <code>'-'</code> 。如果存在，连字符两侧应当都存在小写字母（<code>\"a-b\"</code> 是一个有效单词，但 <code>\"-ab\"</code> 和 <code>\"ab-\"</code> 不是有效单词）。</li>\n",
    "\t<li><strong>至多一个 </strong>标点符号。如果存在，标点符号应当位于 token 的 <strong>末尾</strong> 。</li>\n",
    "</ul>\n",
    "\n",
    "<p>这里给出几个有效单词的例子：<code>\"a-b.\"</code>、<code>\"afad\"</code>、<code>\"ba-c\"</code>、<code>\"a!\"</code> 和 <code>\"!\"</code> 。</p>\n",
    "\n",
    "<p>给你一个字符串 <code>sentence</code> ，请你找出并返回<em> </em><code>sentence</code> 中<strong> 有效单词的数目</strong> 。</p>\n",
    "\n",
    "<p>&nbsp;</p>\n",
    "\n",
    "<p><strong>示例 1：</strong></p>\n",
    "\n",
    "<pre>\n",
    "<strong>输入：</strong>sentence = \"<em><strong>cat</strong></em> <em><strong>and</strong></em>  <em><strong>dog</strong></em>\"\n",
    "<strong>输出：</strong>3\n",
    "<strong>解释：</strong>句子中的有效单词是 \"cat\"、\"and\" 和 \"dog\"\n",
    "</pre>\n",
    "\n",
    "<p><strong>示例 2：</strong></p>\n",
    "\n",
    "<pre>\n",
    "<strong>输入：</strong>sentence = \"!this  1-s b8d!\"\n",
    "<strong>输出：</strong>0\n",
    "<strong>解释：</strong>句子中没有有效单词\n",
    "\"!this\" 不是有效单词，因为它以一个标点开头\n",
    "\"1-s\" 和 \"b8d\" 也不是有效单词，因为它们都包含数字\n",
    "</pre>\n",
    "\n",
    "<p><strong>示例 3：</strong></p>\n",
    "\n",
    "<pre>\n",
    "<strong>输入：</strong>sentence = \"<em><strong>alice</strong></em> <em><strong>and</strong></em>  <em><strong>bob</strong></em> <em><strong>are</strong></em> <em><strong>playing</strong></em> stone-game10\"\n",
    "<strong>输出：</strong>5\n",
    "<strong>解释：</strong>句子中的有效单词是 \"alice\"、\"and\"、\"bob\"、\"are\" 和 \"playing\"\n",
    "\"stone-game10\" 不是有效单词，因为它含有数字\n",
    "</pre>\n",
    "\n",
    "<p>&nbsp;</p>\n",
    "\n",
    "<p><strong>提示：</strong></p>\n",
    "\n",
    "<ul>\n",
    "\t<li><code>1 &lt;= sentence.length &lt;= 1000</code></li>\n",
    "\t<li><code>sentence</code> 由小写英文字母、数字（<code>0-9</code>）、以及字符（<code>' '</code>、<code>'-'</code>、<code>'!'</code>、<code>'.'</code> 和 <code>','</code>）组成</li>\n",
    "\t<li>句子中至少有 <code>1</code> 个 token</li>\n",
    "</ul>\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Description: [number-of-valid-words-in-a-sentence](https://leetcode.cn/problems/number-of-valid-words-in-a-sentence/description/)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Solutions: [number-of-valid-words-in-a-sentence](https://leetcode.cn/problems/number-of-valid-words-in-a-sentence/solutions/)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "test_cases = ['\"cat and  dog\"', '\"!this  1-s b8d!\"', '\"alice and  bob are playing stone-game10\"']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countValidWords(self, sentence: str) -> int:\n",
    "        s=sentence.split(' ')\n",
    "        x=[]\n",
    "        for i in s:\n",
    "            for j in range(len(i)):\n",
    "                if i[j].isdigit() or i.count('-')>1 or (i[j] in ['!','.',','] and j!=len(i)-1) or (i[j]=='-' and j==0) or (i[j]=='-' and j==len(i)-1) or (i[j]=='-' and i[j+1] in ['!','.',',']):\n",
    "                    break\n",
    "            else:\n",
    "                if len(i)!=0:\n",
    "                    x.append(i)\n",
    "        return len(x)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countValidWords(self, sentence: str) -> int:\n",
    "        res = 0\n",
    "        li = sentence.split()\n",
    "        for words in li:\n",
    "            n = len(words)\n",
    "            lcount = 0\n",
    "            for j in range(n):\n",
    "                if words[j].isdigit():\n",
    "                    break\n",
    "                elif words[j] == '-':\n",
    "                    lcount +=1\n",
    "                    if lcount >1 or j == 0 or j == n-1 or not(words[j-1].isalpha() and words[j+1].isalpha()):\n",
    "                        break\n",
    "                elif words[j] in \"!.,\":\n",
    "                    if j != n-1:\n",
    "                        break \n",
    "            else:\n",
    "                res +=1\n",
    "        return res\n",
    "                "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countValidWords(self, sentence: str) -> int:\n",
    "        temp=sentence.split()\n",
    "        \n",
    "        def is_valid(tt):\n",
    "            flag=False\n",
    "            for i,ch in enumerate(tt):\n",
    "                if ch.isdigit() or ch in ',.!' and i<len(tt)-1:\n",
    "                    return False\n",
    "                if ch=='-':\n",
    "                    if flag or i==0 or i==len(tt)-1 or not tt[i-1].islower() or not tt[i+1].islower():\n",
    "                        return False\n",
    "                    flag=True\n",
    "            return True\n",
    "        res=0\n",
    "        for tt in temp:\n",
    "            if is_valid(tt):\n",
    "                res+=1\n",
    "        return res"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countValidWords(self, sentence: str) -> int:\n",
    "        l = sentence.split()\n",
    "        ans = 0\n",
    "        pattern = re.compile(r'''\n",
    "            (?:[,.!]$) |         # 只有一个标点，或者\n",
    "            (?:\n",
    "                (?=([a-z]+))\\1   # 开头必须是字母，这里用固化分组匹配所有字母\n",
    "                (?:-[a-z])?      # 如果遇到了非字母，可能是连字符+字母\n",
    "                (?=([a-z]*))\\2   # 可能又有一串字母\n",
    "                [,.!]?           # 结尾可以有一个标点\n",
    "            )$                  \n",
    "            ''', re.X)\n",
    "\n",
    "        for w in l:\n",
    "            if pattern.match(w):\n",
    "                ans += 1\n",
    "        return ans"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countValidWords(self, sentence: str) -> int:\n",
    "        l = sentence.split()\n",
    "        ans = 0\n",
    "        p_number = re.compile(r'\\d')    # 数字\n",
    "        p_dash = re.compile(r'(?<![a-z])-|-(?![a-z])')  # 前面或后面不是字母的连字符\n",
    "        p_dash2 = re.compile(r'-(?=([^-]*))\\1-')     # 两个连字符\n",
    "        p_punc = re.compile(r'[!.,].')  # 不在末尾的标点\n",
    "        for w in l:\n",
    "            if p_number.search(w) or p_dash.search(w) or p_dash2.search(w) or p_punc.search(w):    \n",
    "                continue\n",
    "            ans += 1\n",
    "        return ans"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countValidWords(self, sentence: str) -> int:\n",
    "        def valid(s: str) -> bool:\n",
    "            hasHyphens = False\n",
    "            for i, ch in enumerate(s):\n",
    "                if ch.isdigit() or ch in \"!.,\" and i < len(s) - 1:\n",
    "                    return False\n",
    "                if ch == '-':\n",
    "                    if hasHyphens or i == 0 or i == len(s) - 1 or not s[i - 1].islower() or not s[i + 1].islower():\n",
    "                        return False\n",
    "                    hasHyphens = True\n",
    "            return True\n",
    "\n",
    "        return sum(valid(s) for s in sentence.split())\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countValidWords(self, sentence: str) -> int:\n",
    "        l = sentence.split()\n",
    "        ans = 0\n",
    "        p_number = re.compile(r'\\d')    # 数字\n",
    "        p_dash = re.compile(r'(?<![a-z])-|-(?![a-z])')  # 前面或后面不是字母的连字符\n",
    "        p_dash2 = re.compile(r'-(?=([^-]*))\\1-')     # 两个连字符\n",
    "        p_punc = re.compile(r'[!.,].')  # 不在末尾的标点\n",
    "        for w in l:\n",
    "            if p_number.search(w) or p_dash.search(w) or p_dash2.search(w) or p_punc.search(w):    \n",
    "                continue\n",
    "            ans += 1\n",
    "        return ans"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countValidWords(self, sentence: str) -> int:\n",
    "        l = sentence.split()\n",
    "        ans = 0\n",
    "        pattern = re.compile(r'''\n",
    "            (?:[,.!]$)|          # 只有一个标点，或者\n",
    "            (?:\n",
    "                (?=([a-z]+))\\1   # 开头必须是字母，这里用固化分组匹配所有字母\n",
    "                (?:-[a-z])?      # 如果遇到了非字母，可能是连字符+字母\n",
    "                (?=([a-z]*))\\2   # 可能又有一串字母\n",
    "                [,.!]?           # 结尾可以有一个标点\n",
    "            )$                  \n",
    "            ''', re.X)\n",
    "\n",
    "        for w in l:\n",
    "            if pattern.match(w):\n",
    "                ans += 1\n",
    "        return ans"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countValidWords(self, sentence: str) -> int:\n",
    "        sls=sentence.split()\n",
    "        ans=0\n",
    "        for i in sls:\n",
    "            if self.isture(i):\n",
    "                ans+=1\n",
    "        return ans\n",
    "    \n",
    "    def isture(self,s):\n",
    "        if len(s)==0:\n",
    "            return False\n",
    "        temp=[]\n",
    "        flag=False\n",
    "        for i in range(len(s)):\n",
    "            if \"a\"<=s[i]<=\"z\":\n",
    "                temp.append(s[i])\n",
    "            elif s[i]==\"-\" and not flag and i<len(s)-1 and len(temp)>0 and \"a\"<=s[i+1]<=\"z\":\n",
    "                temp.append(s[i])\n",
    "                flag=True\n",
    "            elif s[i]==\"!\" or s[i]==\".\" or s[i]==\",\":\n",
    "                if i!=len(s)-1:\n",
    "                    return False\n",
    "            else:\n",
    "                return False\n",
    "        else:\n",
    "            return True\n",
    "\n",
    "\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countValidWords(self, sentence: str) -> int:\n",
    "        res = 0\n",
    "        li = sentence.split()\n",
    "        for words in li:\n",
    "            n = len(words)\n",
    "            lcount = 0\n",
    "            for j in range(n):\n",
    "                if words[j].isdigit():\n",
    "                    break\n",
    "                elif words[j] == '-':\n",
    "                    lcount +=1\n",
    "                    if lcount >1 or j == 0 or j == n-1 or not(words[j-1].isalpha() and words[j+1].isalpha()):\n",
    "                        break\n",
    "                elif words[j] in \"!.,\":\n",
    "                    if j != n-1:\n",
    "                        break \n",
    "            else:\n",
    "                res +=1\n",
    "        return res\n",
    "                "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countValidWords(self, sentence: str) -> int:\n",
    "        l = sentence.split()\n",
    "        ans = 0\n",
    "        pattern = re.compile(r'''\n",
    "            (?:[,.!]$) |            # 只有一个标点，或者\n",
    "            (?:\n",
    "                (?=([a-z]+))\\1      # 开头必须是字母，这里用固化分组匹配所有字母\n",
    "                (?=((?:-[a-z])?))\\2 # 如果遇到了非字母，可能是连字符+字母\n",
    "                (?=([a-z]*))\\3      # 可能又有一串字母\n",
    "                [,.!]?              # 结尾可以有一个标点\n",
    "            )$                  \n",
    "            ''', re.X)\n",
    "        for w in l:\n",
    "            if pattern.match(w):\n",
    "                ans += 1\n",
    "        return ans"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countValidWords(self, sentence: str) -> int:\n",
    "        def valid(s: str) -> bool:\n",
    "            hasHyphens = False\n",
    "            for i, ch in enumerate(s):\n",
    "                if ch.isdigit() or ch in \"!.,\" and i < len(s) - 1:\n",
    "                    return False\n",
    "                if ch == '-':\n",
    "                    if hasHyphens or i == 0 or i == len(s) - 1 or not s[i - 1].islower() or not s[i + 1].islower():\n",
    "                        return False\n",
    "                    hasHyphens = True\n",
    "            return True\n",
    "\n",
    "        return sum(valid(s) for s in sentence.split())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countValidWords(self, sc: str) -> int:\n",
    "        return sum(bool(re.match(r'[a-z]*([a-z]-[a-z]+)?[!.,]?$', w)) for w in sc.split())\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countValidWords(self, sentence: str) -> int:\n",
    "        def helper(word):\n",
    "            n, appear = len(word), False\n",
    "            for i, c in enumerate(word):\n",
    "                if 'a' <= c <= 'z':\n",
    "                    continue\n",
    "                elif c == '-':\n",
    "                    if appear or not i or i == n - 1 or not ('a' <= word[i-1] <= 'z' and 'a' <= word[i+1] <= 'z'):\n",
    "                        return False\n",
    "                    appear = True\n",
    "                elif c in '!.,':\n",
    "                    if i != n - 1:\n",
    "                        return False\n",
    "                else:\n",
    "                    return False\n",
    "            return True\n",
    "\n",
    "        return sum(helper(w) for w in sentence.split(' ') if w)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countValidWords(self, sc: str) -> int:\n",
    "        return sum(bool(re.match(r'[a-z]*([a-z]-[a-z]+)?[!.,]?$', w)) for w in sc.split())\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "find = re.compile(r'(?:(?<=\\s)|(?<=^))([a-z]+\\-[a-z]+|[a-z]+)?(?(1)[\\!\\,\\.]?|[\\!\\,\\.])(?:(?=\\s)|(?=$))')\n",
    "\n",
    "class Solution:\n",
    "    def countValidWords(self, sentence: str) -> int:\n",
    "        return len(find.findall(sentence))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countValidWords(self, sentence: str) -> int:\n",
    "        tok = sentence.split(' ');ans = 0; nums = {'0','1','2','3','4','5','6','7','8','9'}; dot = {'!', '.',','}\n",
    "        for t in tok:\n",
    "            le = len(t)\n",
    "            if le > 0:\n",
    "                if all(tp not in nums for tp in t):\n",
    "                    c_ = t.count('-')\n",
    "                    if c_ > 1:\n",
    "                        continue\n",
    "                    elif c_ == 1:\n",
    "                        ind = t.find('-')\n",
    "                        if ind == 0 or ind == le-1:\n",
    "                            continue#贴边\n",
    "                        if t[ind-1] not in ascii_letters or t[ind+1] not in ascii_letters:\n",
    "                            continue\n",
    "                    cd = 0\n",
    "                    for d in dot:\n",
    "                        cd += t.count(d)\n",
    "                    if cd > 1:\n",
    "                        continue\n",
    "                    elif cd == 1:\n",
    "                        if t[-1] not in dot:\n",
    "                            continue\n",
    "                    ans += 1\n",
    "        return ans\n",
    "                        \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countValidWords(self, sentence: str) -> int:\n",
    "        def helper(word):\n",
    "            n, appear = len(word), False\n",
    "            for i, c in enumerate(word):\n",
    "                if 'a' <= c <= 'z':\n",
    "                    continue\n",
    "                elif c == '-':\n",
    "                    if appear or not i or i == n - 1 or not ('a' <= word[i-1] <= 'z' and 'a' <= word[i+1] <= 'z'):\n",
    "                        return False\n",
    "                    appear = True\n",
    "                elif c in '!.,':\n",
    "                    if i != n - 1:\n",
    "                        return False\n",
    "                else:\n",
    "                    return False\n",
    "            return True\n",
    "        \n",
    "        return sum(helper(w) for w in sentence.split(' ') if w)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countValidWords(self, sentence: str) -> int:\n",
    "        def valid(s: str) -> bool:\n",
    "            hasHyphens = False\n",
    "            for i, ch in enumerate(s):\n",
    "                if ch.isdigit() or ch in \"!.,\" and i < len(s) - 1:\n",
    "                    return False\n",
    "                if ch == '-':\n",
    "                    if hasHyphens or i == 0 or i == len(s) - 1 or not s[i - 1].islower() or not s[i + 1].islower():\n",
    "                        return False\n",
    "                    hasHyphens = True\n",
    "            return True\n",
    "\n",
    "        return sum(valid(s) for s in sentence.split())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countValidWords(self, sentence: str) -> int:\n",
    "        s1 = sentence.split(\" \")\n",
    "        sum = 0 \n",
    "        for i in s1:\n",
    "            if i:\n",
    "                if (bool(re.match('[a-z]*([a-z]-[a-z]+)?[!.,]?$',i))):\n",
    "                    sum+=1\n",
    "        return sum        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countValidWords(self, sentence: str) -> int:\n",
    "        count = 0\n",
    "        tokens = sentence.split()\n",
    "        for token in tokens:\n",
    "            # 小写字母+连字符+标点\n",
    "            # 小写字母+连字符\n",
    "            # 小写字母+标点\n",
    "            # 连字符出现次数>1，不合法\n",
    "            flag = True\n",
    "            for num in '0123456789':\n",
    "                if num in token:\n",
    "                    flag = False\n",
    "                    break\n",
    "            if not flag:\n",
    "                continue\n",
    "            if token.count(\"-\") > 1:\n",
    "                continue\n",
    "            elif token.count(\"-\") == 1:\n",
    "                # find，先查找下标， 若在末尾或0则不合法\n",
    "                idx = token.find(\"-\")\n",
    "                if idx == 0 or idx == len(token)-1:\n",
    "                    continue\n",
    "                elif not('a' <= token[idx-1] <= 'z' and 'a' <= token[idx+1] <= 'z'):\n",
    "                    continue\n",
    "            if token.count('!') + token.count('.') + token.count(',') >1:\n",
    "                continue\n",
    "            else:\n",
    "                if token.find('!') != -1 and token.find('!') != len(token) -1:\n",
    "                    continue\n",
    "                if token.find('.') != -1 and token.find('.') != len(token) -1:\n",
    "                    continue\n",
    "                if token.find(',') != -1 and token.find(',') != len(token) -1:\n",
    "                    continue\n",
    "            # print(token)\n",
    "            count+=1\n",
    "        return count"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countValidWords(self, sentence: str) -> int:\n",
    "        s0=[chr(i) for i in range(ord('a'),1+ord('z'))]\n",
    "        s1=s0+['-']\n",
    "        s2=['!','.',',']\n",
    "        res=0\n",
    "        for word in sentence.split():\n",
    "            n=len(word)\n",
    "            flag=0\n",
    "            for i,s in enumerate(word):\n",
    "                if  i<=n-2 and s not in s1: break\n",
    "                if s=='-':\n",
    "                    if flag: break\n",
    "                    if i==0 or i==n-1 or word[i-1] not in s0 or word[i+1] not in s0: break\n",
    "                    flag=1\n",
    "                if i==n-1 and s in s1+s2:res+=1\n",
    "        return res"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countValidWords(self, sentence: str) -> int:\n",
    "        l = sentence.split()\n",
    "        pattern = re.compile(r'''\n",
    "            (?:[,.!]$) |            # 只有一个标点，或者\n",
    "            (?:\n",
    "                (?=([a-z]+))\\1      # 开头必须是字母，这里用固化分组匹配所有字母\n",
    "                (?=((?:-[a-z])?))\\2 # 如果遇到了非字母，可能是连字符+字母\n",
    "                (?=([a-z]*))\\3      # 可能又有一串字母\n",
    "                [,.!]?              # 结尾可以有一个标点\n",
    "            )$                  \n",
    "            ''', re.X)\n",
    "\n",
    "        ans = 0\n",
    "        for w in l:\n",
    "            if pattern.match(w):\n",
    "                ans += 1\n",
    "        return ans"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countValidWords(self, sentence: str) -> int:\n",
    "        sl=sentence.split()\n",
    "        count=0\n",
    "        for i in sl:\n",
    "            flag=True\n",
    "            signal=['!','.',',']\n",
    "            for j in signal:                                \n",
    "                if j in i and i.index(j)!=len(i)-1:\n",
    "                    flag=False\n",
    "            if '-' in i:\n",
    "                if i[0]=='-' or i[-1]=='-' or i.count('-')>1 :\n",
    "                    flag=False\n",
    "                else:  \n",
    "                    if i[i.index('-')-1] in signal or i[i.index('-')+1] in signal:\n",
    "                        flag=False\n",
    "            for j in i:\n",
    "                if j.isdigit():\n",
    "                    flag=False            \n",
    "            if flag:\n",
    "                #print(i)\n",
    "                count+=1\n",
    "        return count"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countValidWords(self, sentence: str) -> int:\n",
    "        # 小写字母（'a' 到 'z'）、连字符（'-'）、标点符号（'!'、'.' 和 ','）\n",
    "        s = sentence.split(\" \")\n",
    "        cnt = 0\n",
    "        for si in s:\n",
    "            if len(si) > 0 and string.digits not in si:  # 不含数字\n",
    "                idx1 = si.find(\"!\")\n",
    "                idx2 = si.find(\".\")\n",
    "                idx3 = si.find(\",\")\n",
    "                last_idx = len(si) - 1\n",
    "                if (idx1 != -1 and idx1 != last_idx) or (idx2 != -1 and idx2 != last_idx) or (idx3 != -1 and idx3 != last_idx):  # 条件3：标点在最后\n",
    "                    continue\n",
    "                cnt1 = si.count(\"-\")\n",
    "                if cnt1 > 1: continue\n",
    "                if cnt1 == 1:\n",
    "                    idx = si.find(\"-\")\n",
    "                    if idx == 0 or idx ==last_idx:\n",
    "                        continue\n",
    "                    if not (si[idx-1].islower() and si[idx+1].islower()):\n",
    "                        continue\n",
    "                sin = si.replace(\"-\", \"\").replace(\"!\", \"\").replace(\".\", \"\").replace(\",\", \"\")\n",
    "                if len(sin) > 0 and not sin.isalpha():\n",
    "                    continue\n",
    "                cnt += 1\n",
    "        return cnt\n",
    "\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countValidWords(self, sentence: str) -> int:\n",
    "        def valid(s:str)-> bool:\n",
    "            hasHyphens = False\n",
    "            for i,ch in enumerate(s):\n",
    "                if ch.isdigit() or ch in \"!.,\" and i<len(s)-1:\n",
    "                    return False\n",
    "                if ch=='-':\n",
    "                    if hasHyphens or i==0 or i==len(s)-1 or not s[i-1].islower() or not s[i+1].islower():\n",
    "                        return False\n",
    "                    hasHyphens = True\n",
    "            return True\n",
    "        return sum(valid(s) for s in sentence.split())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countValidWords(self, sentence: str) -> int:\n",
    "        return sum(bool(re.match(r'[a-z]*([a-z]-[a-z]+)?[!.,]?$', word)) for word in sentence.split(' ') if word)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countValidWords(self, sentence: str) -> int:\n",
    "        # def judge(w):\n",
    "        #     comma = ('!', '.', ',')\n",
    "        #     if w[-1] in comma:\n",
    "        #         w = w[:-1]\n",
    "        #     if w and (w[0] == '-' or w[-1] == '-'):\n",
    "        #         return 0\n",
    "        #     w = w.split('-')\n",
    "        #     if len(w) > 2:\n",
    "        #         return 0\n",
    "        #     w = ''.join(w)\n",
    "        #     return all(ord('a') <= ord(ch) <= ord('z') for ch in w)\n",
    "\n",
    "        # return sum(judge(w) for w in sentence.split())\n",
    "\n",
    "        # ----------------------\n",
    "        return sum(bool(re.match(r'[a-z]*([a-z]-[a-z]+)?[!.,]?$', word)) for word in sentence.split(\" \") if word)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countValidWords(self, sentence: str) -> int:\n",
    "        ans = 0\n",
    "        for word in sentence.split():            \n",
    "            if all(c not in word or (c in word and word.count(c) == 1 and word[-1] == c) for c in '!,.'): \n",
    "                if word[-1] in '!,.':word = word[:-1]\n",
    "                lenw = len(word)\n",
    "                if lenw == 0: ans += 1\n",
    "                elif '-' not in word or ('-' in word and word.count('-') == 1 and 0 < word.index('-') < lenw - 1): \n",
    "                    ans += word.replace('-', 'a').isalpha() and word.islower()\n",
    "        return ans\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countValidWords(self, sentence: str) -> int:\n",
    "        l = sentence.split()\n",
    "        ans = 0\n",
    "        pattern = re.compile(r'''\n",
    "            (?:[,.!]$) |            # 只有一个标点，或者\n",
    "            (?:\n",
    "                (?=([a-z]+))\\1      # 开头必须是字母，这里用固化分组匹配所有字母\n",
    "                (?=((?:-[a-z])?))\\2 # 如果遇到了非字母，可能是连字符+字母\n",
    "                (?=([a-z]*))\\3      # 可能又有一串字母\n",
    "                [,.!]?              # 结尾可以有一个标点\n",
    "            )$                  \n",
    "            ''', re.X)\n",
    "        for w in l:\n",
    "            if pattern.match(w):\n",
    "                ans += 1\n",
    "        return ans"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countValidWords(self, sentence: str) -> int:\n",
    "        def judge(w):\n",
    "            comma = ('!', '.', ',')\n",
    "            if w[-1] in comma:\n",
    "                w = w[:-1]\n",
    "            if w and (w[0] == '-' or w[-1] == '-'):\n",
    "                return 0\n",
    "            w = w.split('-')\n",
    "            if len(w) > 2:\n",
    "                return 0\n",
    "            w = ''.join(w)\n",
    "            return all(ord('a') <= ord(ch) <= ord('z') for ch in w)\n",
    "\n",
    "        return sum(judge(w) for w in sentence.split())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countValidWords(self, sentence: str) -> int:\n",
    "        l = sentence.split()\n",
    "        ans = 0\n",
    "        pattern = re.compile(r'^(?:[,.!]|(?:(?=([a-z]+))\\1(-[a-z]+)?[,.!]?))$')\n",
    "        for w in l:\n",
    "            if pattern.match(w):\n",
    "                ans += 1\n",
    "        return ans"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countValidWords(self, sentence: str) -> int:\n",
    "        l = sentence.split()\n",
    "        pattern = re.compile(r'''\n",
    "            ^(?:[,.!]|               # 只有一个标点，或者\n",
    "                (?:\n",
    "                    (?=([a-z]+))\\1   # 开头必须是字母，这里用固化分组匹配所有字母\n",
    "                    (?:-[a-z])?      # 如果遇到了非字母，可能是连字符+字母\n",
    "                    (?=([a-z]*))\\2   # 又是一串字母\n",
    "                    [,.!]?)          # 结尾可以有一个标点\n",
    "            )$                     \n",
    "            ''', re.X)\n",
    "\n",
    "        return sum(1 for w in l if pattern.match(w))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countValidWords(self, sentence: str) -> int:\n",
    "        l = sentence.split()\n",
    "        ans = 0\n",
    "        pattern = re.compile(r'''\n",
    "            ^(?:[,.!]|               # 只有一个标点，或者\n",
    "                (?:\n",
    "                    (?=([a-z]+))\\1   # 开头必须是字母，这里用固化分组匹配所有字母\n",
    "                    (?:-[a-z])?      # 如果遇到了非字母，可能是连字符+字母\n",
    "                    (?=([a-z]*))\\2   # 又是一串字母\n",
    "                    [,.!]?)          # 结尾可以有一个标点\n",
    "            )$                     \n",
    "            ''', re.X)\n",
    "        for w in l:\n",
    "            if pattern.match(w):\n",
    "                ans += 1\n",
    "        return ans"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countValidWords(self, sentence: str) -> int:\n",
    "        tok = sentence.split(' ');ans = 0; nums = {'0','1','2','3','4','5','6','7','8','9'}; dot = {'!', '.',','}\n",
    "        for t in tok:\n",
    "            le = len(t)\n",
    "            if le > 0:\n",
    "                if all(tp not in nums for tp in t):\n",
    "                    c_ = t.count('-')\n",
    "                    if c_ > 1:\n",
    "                        continue\n",
    "                    elif c_ == 1:\n",
    "                        ind = t.find('-')\n",
    "                        if (ind == 0 or ind == le-1) or (t[ind-1] not in ascii_letters or t[ind+1] not in ascii_letters):\n",
    "                            continue\n",
    "                    cd = 0\n",
    "                    for d in dot:\n",
    "                        cd += t.count(d)\n",
    "                    if cd > 1 or (cd == 1 and t[-1] not in dot):\n",
    "                        continue\n",
    "                    ans += 1\n",
    "        return ans\n",
    "                        \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countValidWords(self,sentence: str) -> int:\n",
    "        def check(word):\n",
    "            if not word or len(word) == 0:\n",
    "                return False\n",
    "            n = len(word)\n",
    "            flag = False\n",
    "            for i in range(n):\n",
    "    \n",
    "\n",
    "                if ord('0') <= ord(word[i]) <= ord('9'):\n",
    "                    return False\n",
    "                elif word[i] == '-':\n",
    "                    if flag:\n",
    "                        return False\n",
    "                    flag = True\n",
    "                    if i == 0 or i == n - 1:\n",
    "                        return False\n",
    "\n",
    "                    if not ord('a') <= ord(word[i - 1]) <= ord('z') or  not ord('a') <= ord(word[i + 1]) <= ord('z'):\n",
    "                        return False\n",
    "                elif (not ord('a') <= ord(word[i]) <= ord('z')) and  (i != n - 1):\n",
    "                    return False\n",
    "\n",
    "            return True\n",
    "\n",
    "        words = sentence.split(' ')\n",
    "        ans = 0\n",
    "        for word in words:\n",
    "            if check(word.strip()):\n",
    "                ans += 1\n",
    "        return ans"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "import re\n",
    "class Solution:\n",
    "    def countValidWords(self, sentence: str) -> int:\n",
    "        lists = sentence.split()\n",
    "        number = 0\n",
    "\n",
    "        for word in lists:\n",
    "            # 两种匹配模式，「 | 」 左边为有连接号的更长匹配，右边仅为单词与标点符号的匹配\n",
    "            p = re.match(r'[a-z]+-[a-z]+[!.,]?|[a-z]*[!.,]?', word)\n",
    "            if p and p.group() == word:\n",
    "                number += 1\n",
    "        return number"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countValidWords(self, sentence: str) -> int:\n",
    "        def valid(s: str) -> bool:\n",
    "            hasHyphens = False\n",
    "            for i, ch in enumerate(s):\n",
    "                if ch.isdigit() or ch in \"!.,\" and i < len(s) - 1:\n",
    "                    return False\n",
    "                if ch == '-':\n",
    "                    if hasHyphens or i == 0 or i == len(s) - 1 or not s[i - 1].islower() or not s[i + 1].islower():\n",
    "                        return False\n",
    "                    hasHyphens = True\n",
    "            return True\n",
    "\n",
    "        return sum(valid(s) for s in sentence.split())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countValidWords(self, sentence: str) -> int:\n",
    "        l = sentence.split()\n",
    "        ans = 0\n",
    "        pattern = re.compile(r'''\n",
    "            (?:[,.!]$) |            # 只有一个标点，或者\n",
    "            (?:\n",
    "                (?=([a-z]+))\\1      # 开头必须是字母，这里用固化分组匹配所有字母\n",
    "                (?:(?=(-[a-z]))\\2)? # 如果遇到了非字母，可能是连字符+字母\n",
    "                (?=([a-z]*))\\3      # 可能又有一串字母\n",
    "                [,.!]?              # 结尾可以有一个标点\n",
    "            )$                  \n",
    "            ''', re.X)\n",
    "        for w in l:\n",
    "            if pattern.match(w):\n",
    "                ans += 1\n",
    "        return ans"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countValidWords(self, sentence: str) -> int:\n",
    "        ans = 0\n",
    "        for word in sentence.split():            \n",
    "            if all(c not in word or (c in word and word.count(c) == 1 and word[-1] == c) for c in '!,.'): \n",
    "                if word[-1] in '!,.':word = word[:-1]\n",
    "                lenw = len(word)\n",
    "                if lenw == 0: ans += 1\n",
    "                elif '-' not in word or ('-' in word and word.count('-') == 1 and 0 < word.index('-') < lenw - 1): \n",
    "                    ans += word.replace('-', 'a').isalpha() and word.islower()\n",
    "        return ans\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countValidWords(self, sentence: str) -> int:\n",
    "        ans = 0\n",
    "        for word in sentence.split():            \n",
    "            if all(c not in word or (c in word and word.count(c) == 1 and word[-1] == c) for c in '!,.'): \n",
    "                if word[-1] in '!,.':word = word[:-1]\n",
    "                lenw = len(word)\n",
    "                if lenw == 0: ans += 1\n",
    "                elif '-' not in word or ('-' in word and word.count('-') == 1 and 0 < word.index('-') < lenw - 1): \n",
    "                    ans += word.replace('-', 'a').isalpha() and word.islower()\n",
    "        return ans\n",
    "\n",
    "# 作者：_G_\n",
    "# 链接：https://leetcode.cn/problems/number-of-valid-words-in-a-sentence/solutions/2325801/mo-ni-zi-fu-chuan-pi-pei-tao-lun-ji-ke-b-qwek/\n",
    "# 来源：力扣（LeetCode）\n",
    "# 著作权归作者所有。商业转载请联系作者获得授权，非商业转载请注明出处。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countValidWords(self, sentence: str) -> int:\n",
    "        l = sentence.split()\n",
    "        ans = 0\n",
    "        pattern = re.compile(r'''\n",
    "            (?:[,.!]$) |            # 只有一个标点，或者\n",
    "            (?:\n",
    "                (?=([a-z]+))\\1      # 开头必须是字母，这里用固化分组匹配所有字母\n",
    "                (?=((?:-[a-z])?))\\2 # 如果遇到了非字母，可能是连字符+字母\n",
    "                (?=([a-z]*))\\3      # 可能又有一串字母\n",
    "                [,.!]?              # 结尾可以有一个标点\n",
    "            )$                  \n",
    "            ''', re.X)\n",
    "            \n",
    "        return sum(1 for w in l if pattern.match(w))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countValidWords(self, sentence: str) -> int:\n",
    "        def helper(word):\n",
    "            n, appear = len(word), False\n",
    "            for i, c in enumerate(word):\n",
    "                if 'a' <= c <= 'z':\n",
    "                    continue\n",
    "                elif c == '-':\n",
    "                    if appear or not i or i == n - 1 or not ('a' <= word[i-1] <= 'z' and 'a' <= word[i+1] <= 'z'):\n",
    "                        return False\n",
    "                    appear = True\n",
    "                elif c in '!.,':\n",
    "                    if i != n - 1:\n",
    "                        return False\n",
    "                else:\n",
    "                    return False\n",
    "            return True\n",
    "        \n",
    "        return sum(helper(w) for w in sentence.split(' ') if w)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countValidWords(self, sentence: str) -> int:\n",
    "        def isWord(s):\n",
    "            c = 0\n",
    "            for i in range(len(s)):\n",
    "                if s[i].isdigit():\n",
    "                    return False\n",
    "                if s[i] == \"-\":\n",
    "                    if i == 0 or i == len(s) - 1:\n",
    "                        return False\n",
    "                    else:\n",
    "                        if not s[i - 1].isalpha() or not s[i + 1].isalpha():\n",
    "                            return False\n",
    "                        else:\n",
    "                            c += 1\n",
    "                if s[i] in [\"!\", \".\", \",\"] and i != len(s) - 1:\n",
    "                    return False\n",
    "            if c > 1:\n",
    "                return False\n",
    "            return True\n",
    "\n",
    "        ans = 0\n",
    "        for word in sentence.split(\" \"):\n",
    "            if word:\n",
    "                if isWord(word):\n",
    "                    print(word)\n",
    "                    ans += 1\n",
    "        return ans"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countValidWords(self, sentence: str) -> int:\n",
    "        l = sentence.split()\n",
    "        ans = 0\n",
    "        pattern = re.compile(r'''\n",
    "            (?:[,.!]$) |            # 只有一个标点，或者\n",
    "            (?:\n",
    "                (?=([a-z]+))\\1      # 开头必须是字母，这里用固化分组匹配所有字母\n",
    "                (?=((?:-[a-z])?))\\2 # 如果遇到了非字母，可能是连字符+字母\n",
    "                (?=([a-z]*))\\3      # 可能又有一串字母\n",
    "                [,.!]?              # 结尾可以有一个标点\n",
    "            )$                  \n",
    "            ''', re.X)\n",
    "        for w in l:\n",
    "            if pattern.match(w):\n",
    "                ans += 1\n",
    "        return ans"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countValidWords(self, sentence: str) -> int:\n",
    "        def check(s):\n",
    "            n, flag = len(s), False\n",
    "            for i, c in enumerate(s):\n",
    "                if c.isalpha(): continue\n",
    "                elif c == '-':\n",
    "                    if flag or not i or i == n - 1 or not(s[i - 1].isalpha() and s[i + 1].isalpha()):\n",
    "                        return False\n",
    "                    flag = True\n",
    "                elif c in '!.,':\n",
    "                    if i != n - 1:\n",
    "                        return False\n",
    "                else:\n",
    "                    return False\n",
    "            return True\n",
    "        \n",
    "        return sum(check(w) for w in sentence.split())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countValidWords(self, sentence: str) -> int:\n",
    "        l = sentence.split()\n",
    "        ans = 0\n",
    "        pattern = re.compile(r'''\n",
    "            (?:[,.!]$) |         # 只有一个标点，或者\n",
    "            (?:\n",
    "                (?=([a-z]+))\\1   # 开头必须是字母，这里用固化分组匹配所有字母\n",
    "                (?:-[a-z])?      # 如果遇到了非字母，可能是连字符+字母\n",
    "                [a-z]*           # 可能又有一串字母\n",
    "                [,.!]?           # 结尾可以有一个标点\n",
    "            )$                  \n",
    "            ''', re.X)\n",
    "\n",
    "        for w in l:\n",
    "            if pattern.match(w):\n",
    "                ans += 1\n",
    "        return ans"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countValidWords(self, sentence: str) -> int:\n",
    "        words = sentence.split()\n",
    "        ans = 0\n",
    "        for word in words:\n",
    "            if word[0] == '-' or word[-1] == '-':\n",
    "                continue\n",
    "            else:\n",
    "                flag = False\n",
    "                for number in \"1234567890\":\n",
    "                    if number in word:\n",
    "                        flag = True\n",
    "                        break\n",
    "                if flag:\n",
    "                    continue\n",
    "                else:\n",
    "                    count = 0\n",
    "                    for index, ch in enumerate(word):\n",
    "                        if ch == '-':\n",
    "                            if not ('a' <= word[index + 1] <= 'z') \\\n",
    "                            or not ('a' <= word[index - 1] <= 'z'):\n",
    "                                # '-'的左右不是字母\n",
    "                                count = 2\n",
    "                                break\n",
    "                            count += 1\n",
    "                        elif ch == '!' or ch == ',' or ch == '.':\n",
    "                            if index < len(word) - 1:\n",
    "                                count = 2  # 利用count来终止本次检查\n",
    "                    if count > 1:\n",
    "                        continue\n",
    "                    else:\n",
    "                        ans += 1\n",
    "        return ans"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countValidWords(self, sentence: str) -> int:\n",
    "        PUNCT = ['!', '.', ',']\n",
    "        HYPHEN = '-'\n",
    "\n",
    "        def isWord(s: str) -> bool:\n",
    "            haveHyphen = False\n",
    "            for i, char in enumerate(s):\n",
    "                if char in PUNCT and i != len(s)-1: # 标点符号不在单词末尾\n",
    "                    return False\n",
    "                if ord('0') <= ord(char) <= ord('9'): # 数字\n",
    "                    return False\n",
    "                if char == HYPHEN: # 连字符\n",
    "                    if i == 0 or i == len(s) - 1 or haveHyphen==True or s[i+1] in PUNCT:\n",
    "                        return False\n",
    "                    haveHyphen = True\n",
    "            return True\n",
    "        \n",
    "        num = 0\n",
    "        for word in sentence.split():\n",
    "            if isWord(word):\n",
    "                num += 1\n",
    "        return num\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countValidWords(self, sentence: str) -> int:\n",
    "        l = sentence.split()\n",
    "        ans = 0\n",
    "        pattern = re.compile(r'''\n",
    "            ^(?:[,.!]|               # 只有一个标点，或者\n",
    "                (?:\n",
    "                    (?=([a-z]+))\\1   # 开头必须是字母，这里用固化分组匹配所有字母\n",
    "                    (?:-[a-z])?      # 如果遇到了非字母，可能是连字符+字母\n",
    "                    (?=([a-z]*))\\2   # 又是一串字母\n",
    "                    [,.!]?)          # 结尾可以有一个标点\n",
    "            )$                     \n",
    "            ''', re.X)\n",
    "            \n",
    "        for w in l:\n",
    "            if pattern.match(w):\n",
    "                ans += 1\n",
    "        return ans"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countValidWords(self, sentence: str) -> int:\n",
    "        def isWord(s):\n",
    "            c = 0\n",
    "            for i in range(len(s)):\n",
    "                if s[i].isdigit():\n",
    "                    return False\n",
    "                if s[i] == \"-\":\n",
    "                    if i == 0 or i == len(s) - 1:\n",
    "                        return False\n",
    "                    else:\n",
    "                        if not s[i - 1].isalpha() or not s[i + 1].isalpha():\n",
    "                            return False\n",
    "                        else:\n",
    "                            c += 1\n",
    "                if s[i] in [\"!\", \".\", \",\"]:\n",
    "                    if i != len(s) - 1:\n",
    "                        return False\n",
    "            if c > 1:\n",
    "                return False\n",
    "            return True\n",
    "\n",
    "        ans = 0\n",
    "        for word in sentence.split(\" \"):\n",
    "            if word:\n",
    "                if isWord(word):\n",
    "                    print(word)\n",
    "                    ans += 1\n",
    "        return ans"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countValidWords(self, sentence: str) -> int:\n",
    "        \n",
    "        def check(word):\n",
    "            if word[0]=='-' or word[-1]=='-':\n",
    "                return False\n",
    "            ed = len(word)-1 if word[-1] in {'!','.',','} else len(word)\n",
    "            count_ = 0\n",
    "            for i in range(ed):\n",
    "                if not ord('a')<=ord(word[i])<=ord('z'):\n",
    "                    if word[i]=='-' and i!=ed-1:\n",
    "                        count_ += 1\n",
    "                    else:\n",
    "                        return False\n",
    "            return count_<=1\n",
    "        \n",
    "        return sum(1 for word in sentence.split() if check(word))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countValidWords(self, sentence: str) -> int:\n",
    "        p1, p2 = 0, 0\n",
    "        result = 0\n",
    "        words = sentence.split()\n",
    "        regx = r'^([a-z])*([a-z]+(-)[a-z]+)?(([!|.|,])?)$'\n",
    "        for word in words :\n",
    "            p = re.match(regx,word)\n",
    "            if p and p.group(0) == word :\n",
    "                result += 1\n",
    "            pass\n",
    "\n",
    "        return result\n",
    "        pass"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countValidWords(self, sentence: str) -> int:\n",
    "        words = sentence.split(\" \")\n",
    "        count = 0\n",
    "        for i in words:\n",
    "            if i and re.match(r\"[a-z]*([a-z]-[a-z])?[a-z]*[!\\.,]?$\", i):\n",
    "                count += 1\n",
    "        return count"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countValidWords(self, sentence: str) -> int:\n",
    "        def valid(s: str) -> bool:\n",
    "            hasHyphens = False\n",
    "            for i, ch in enumerate(s):\n",
    "                if ch.isdigit() or ch in \"!.,\" and i < len(s) - 1:\n",
    "                    return False\n",
    "                if ch == '-':\n",
    "                    if hasHyphens or i == 0 or i == len(s) - 1 or not s[i - 1].islower() or not s[i + 1].islower():\n",
    "                        return False\n",
    "                    hasHyphens = True\n",
    "            return True\n",
    "\n",
    "        return sum(valid(s) for s in sentence.split())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countValidWords(self, sentence: str) -> int:\n",
    "        ans=0\n",
    "        for word in sentence.split():\n",
    "            if all(c not in word or (c in word and word.count(c)==1 and word[-1]==c) for c in '!,.'):\n",
    "                if word[-1] in '!,.':word=word[:-1]\n",
    "                lenw=len(word)\n",
    "                if lenw==0:ans+=1\n",
    "                elif '-' not in word or('-' in word and word.count('-')==1 and 0<word.index('-')<lenw-1):\n",
    "                    ans+=word.replace('-','a').isalpha() and word.islower()\n",
    "        return ans\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countValidWords(self, sentence: str) -> int:\n",
    "        def valid(s: str) -> bool:\n",
    "            hasHyphens = False\n",
    "            for i, ch in enumerate(s):\n",
    "                if ch.isdigit() or ch in \"!.,\" and i < len(s) - 1:\n",
    "                    return False\n",
    "                if ch == '-':\n",
    "                    if hasHyphens or i == 0 or i == len(s) - 1 or not s[i - 1].islower() or not s[i + 1].islower():\n",
    "                        return False\n",
    "                    hasHyphens = True\n",
    "            return True\n",
    "        return sum(valid(s) for s in sentence.split())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countValidWords(self, sentence: str) -> int:\n",
    "        li=sentence.split()\n",
    "        ret=0\n",
    "        for sent in li:\n",
    "            if '-' in sent :\n",
    "                valid= re.findall('[a-z]+\\-?[a-z]+[!.,]?',sent)\n",
    "            else:\n",
    "                valid= re.findall('[a-z]*[!.,]?',sent)\n",
    "            if valid and valid[0]==sent:\n",
    "                ret +=1 \n",
    "        return ret"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countValidWords(self, sentence: str) -> int:\n",
    "        return sum(bool(re.match(r'[a-z]*([a-z]-[a-z]+)?[!.,]?$', w)) for w in sentence.split())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "import re\n",
    "class Solution:\n",
    "    def countValidWords(self, sentence: str) -> int:\n",
    "        res = 0\n",
    "        for word in sentence.split() :\n",
    "            if re.match(\"[a-z]*([a-z]-[a-z])?[a-z]*[!,.]?$\", word) : \n",
    "                res += 1\n",
    "        return res"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countValidWords(self, sentence: str) -> int:\n",
    "        def func(zz):\n",
    "            count=0\n",
    "            for i,ch in enumerate(zz):\n",
    "                if ch.isdigit() or (ch in '!.,'and i<len(zz)-1):\n",
    "                    return False\n",
    "                if ch=='-':\n",
    "                    if i==0 or i==len(zz)-1 or not zz[i-1].islower() or not zz[i+1].islower():\n",
    "                        return False\n",
    "                    count+=1\n",
    "            if count>=2:\n",
    "                return False\n",
    "            return True\n",
    "            \n",
    "        return sum(func(zz) for zz in sentence.split())\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countValidWords(self, sentence: str) -> int:\n",
    "        def valid(s: str) -> bool:\n",
    "            hasHyphens = False\n",
    "            for i, ch in enumerate(s):\n",
    "                if ch.isdigit() or ch in \"!.,\" and i < len(s) - 1:\n",
    "                    return False\n",
    "                if ch == '-':\n",
    "                    if hasHyphens or i == 0 or i == len(s) - 1 or not s[i - 1].islower() or not s[i + 1].islower():\n",
    "                        return False\n",
    "                    hasHyphens = True\n",
    "            return True\n",
    "\n",
    "        return sum(valid(s) for s in sentence.split())\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countValidWords(self, sentence: str) -> int:\n",
    "        return sum(bool(re.match(r'[a-z]*([a-z]-[a-z]+)?[!.,]?$', word)) for word in sentence.split(\" \") if word)\n",
    "\n",
    "        \n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countValidWords(self, sentence: str) -> int:\n",
    "      temp =sentence.split(' ')\n",
    "      for i in range(temp.count('')):\n",
    "        temp.remove('')\n",
    "      patter = '[a-z]*[!\\.,]?$|[a-z]+-[a-z]+[!\\.,]?$'\n",
    "      count = 0\n",
    "      for i in temp:\n",
    "        result = re.match(patter,i)\n",
    "        if result and len(result.group()) == len(i):\n",
    "          count += 1\n",
    "      return count\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countValidWords(self, sentence: str) -> int:\n",
    "        l = sentence.split()\n",
    "        ans = 0\n",
    "        pattern = re.compile(r'''\n",
    "            (?:[,.!]$) |            # 只有一个标点，或者\n",
    "            (?:\n",
    "                (?=([a-z]+))\\1      # 开头必须是字母，这里用固化分组匹配所有字母\n",
    "                (?=((?:-[a-z])?))\\2 # 如果遇到了非字母，可能是连字符+字母\n",
    "                (?=([a-z]*))\\3      # 可能又有一串字母\n",
    "                [,.!]?              # 结尾可以有一个标点\n",
    "            )$                  \n",
    "            ''', re.X)\n",
    "        for w in l:\n",
    "            if pattern.match(w):\n",
    "                ans += 1\n",
    "        return ans"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countValidWords(self, sentence: str) -> int:\n",
    "        def valid(s: str) -> bool:\n",
    "            hasHyphens = False\n",
    "            for i, ch in enumerate(s):\n",
    "                if ch.isdigit() or ch in \"!.,\" and i < len(s) - 1:\n",
    "                    return False\n",
    "                if ch == '-':\n",
    "                    if hasHyphens or i == 0 or i == len(s) - 1 or not s[i - 1].islower() or not s[i + 1].islower():\n",
    "                        return False\n",
    "                    hasHyphens = True\n",
    "            return True\n",
    "\n",
    "        return sum(valid(s) for s in sentence.split())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countValidWords(self, sentence: str) -> int:\n",
    "        pattern = re.compile(r'''\n",
    "            (?:[,.!]$) |            # 只有一个标点，或者\n",
    "            (?:\n",
    "                (?=([a-z]+))\\1      # 开头必须是字母，这里用固化分组匹配所有字母\n",
    "                (?=((?:-[a-z])?))\\2 # 如果遇到了非字母，可能是连字符+字母\n",
    "                (?=([a-z]*))\\3      # 可能又有一串字母\n",
    "                [,.!]?              # 结尾可以有一个标点\n",
    "            )$                  \n",
    "            ''', re.X)\n",
    "\n",
    "        return sum(1 for w in sentence.split() if pattern.match(w))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countValidWords(self, sentence: str) -> int:\n",
    "        words = sentence.split()\n",
    "        res = 0\n",
    "        \n",
    "        signs = ['!', '.', ',']\n",
    "        \n",
    "        for num in words:\n",
    "            ok = True\n",
    "\n",
    "            #----不能有数字\n",
    "            for x in num:\n",
    "                if x.isdigit():\n",
    "                    ok = False\n",
    "                    break\n",
    "\n",
    "            #----至多一个标点符号\n",
    "            sign_cnt = 0\n",
    "            for x in num:\n",
    "                if x in signs:\n",
    "                    sign_cnt += 1\n",
    "                    if sign_cnt > 1:\n",
    "                        ok = False\n",
    "                        break\n",
    "            #----标点符号应该在末尾\n",
    "            if sign_cnt == 1:\n",
    "                if num[-1] not in signs:\n",
    "                    ok = False\n",
    "            \n",
    "            #----至多一个连字符\n",
    "            a = 0\n",
    "            for x in num:\n",
    "                if x == '-':\n",
    "                    a += 1\n",
    "                    if a > 1:\n",
    "                        ok = False\n",
    "                        break\n",
    "            #----两字符相册都是小写字母\n",
    "            if a == 1:\n",
    "                for i in range(len(num)):\n",
    "                    if num[i] == '-':\n",
    "                        if not(0 <= i - 1 and num[i - 1].isalpha() and i + 1 < len(num) and num[i + 1].isalpha()):\n",
    "                            ok = False\n",
    "            \n",
    "            if ok == True:\n",
    "                res += 1\n",
    "        return res\n",
    "\n",
    "\n",
    "\n",
    "        \n",
    "\n",
    "\n",
    "                \n",
    "\n",
    "                    \n",
    "\n",
    "\n",
    "        \n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countValidWords(self, sentence: str) -> int:\n",
    "        def check(s):\n",
    "            m = Counter(s)\n",
    "            if m['!'] + m['.'] + m[','] > 1 or m['-'] > 1 or s[0] == '-' or s[-1] == '-' or (m['!'] + m['.'] + m[','] == 1 and s[-1] not in '!.,') :\n",
    "                return False\n",
    "            for i in range(10):\n",
    "                if m[str(i)]:\n",
    "                    return False\n",
    "                \n",
    "            if m['-']:\n",
    "                for i in range(1, len(s)-1):\n",
    "                    if s[i] == '-' and not (0 <= ord(s[i-1])-ord(\"a\") < 26 and 0 <= ord(s[i+1])-ord(\"a\") < 26):\n",
    "                        return False\n",
    "            return True\n",
    "        \n",
    "        return sum(check(s) for s in sentence.split())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countValidWords(self, sentence: str) -> int:\n",
    "        def check(word):\n",
    "            word = list(word)\n",
    "            if word.count('-')>1:\n",
    "                return False\n",
    "            n = len(word)\n",
    "            for i, char in enumerate(word):\n",
    "                if char == '-':\n",
    "                    if i == 0 or i == n-1:\n",
    "                        return False\n",
    "                    if not(word[i-1].isalpha() and word[i+1].isalpha()):\n",
    "                        return False\n",
    "                elif char != char.lower():\n",
    "                    return False\n",
    "                elif char.isdigit():\n",
    "                    return False\n",
    "                elif not char.isalpha():\n",
    "                    if i != n-1:\n",
    "                        return False\n",
    "            return True\n",
    "\n",
    "\n",
    "        s = sentence.split()\n",
    "        ans = 0\n",
    "        for word in s:\n",
    "            if check(word):\n",
    "                ans += 1\n",
    "        return ans\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def countValidWords(self, sentence: str) -> int:\n",
    "        count = 0\n",
    "        for word in sentence.split():\n",
    "            flag = True\n",
    "            print(word)\n",
    "            for c in word:\n",
    "                if c in '0123456789':\n",
    "                    flag = False\n",
    "                    break\n",
    "            for c in word[:-1]:\n",
    "                if c in '!.,':\n",
    "                    flag = False\n",
    "                    break\n",
    "            parts = word.split('-')\n",
    "            if len(parts) > 2:\n",
    "                flag = False\n",
    "            if len(parts) == 2:\n",
    "                if len(parts[0]) == 0 or len(parts[1]) == 0 or \\\n",
    "                (len(parts[1]) == 1 and parts[1] in '!.,'):\n",
    "                    flag = False\n",
    "            if flag:\n",
    "                count += 1\n",
    "        return count\n"
   ]
  }
 ],
 "metadata": {},
 "nbformat": 4,
 "nbformat_minor": 2
}
